# Copyright (C) Nicola Bizzoca   2006/2007  <hannibal_smith@users.sourceforge.net>
# Copyright (C) Simone Economo   2006/2007  <ekoes@users.sourceforge.net>
# 
#    This file is part of Absynth-FTP.
#
#    Absynth-FTP is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    Absynth-FTP is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import gtk, gobject

class rowStore:
    
    def __init__(self, row, iter):
        self.row, self.iter = row, iter
    
class colStore:
    
    def __init__(self, col, rend, model):
        self.col, self.rend, self.model = col, rend, model

class genericTreeView:
    
    def __init__(self, features):
        self.__features = features
        self.columns, self.rows = {}, {}
        self.count = {"cols": 0, "rows": 0 }
        self.widget = gtk.TreeView()
        
    def __addBaseColumn(self, name, content, visible, resizable, width):
        contents = {
            "img" : "CellRendererPixbuf",
            "txt" : "CellRendererText",
            "pgr" : "CellRendererProgress",
        }
        renderer = getattr(gtk, contents[content])()
        column = gtk.TreeViewColumn(name, renderer)
        column.set_visible(visible)
        column.set_resizable(resizable)
        if width is None:
            column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        else:
            if resizable is True:
                column.set_min_width(width)
            else:
                column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
                column.set_fixed_width(width)
        return column, renderer
    
    def addTextColumn(self, name, model, visible, resizable, width = None, editable = False, editableHandler = None):
        column, renderer = self.__addBaseColumn(name, "txt", visible, resizable, width)
        column.set_attributes(renderer, text = self.count["cols"])
        if editable == True:
            renderer.set_property('editable', editable)
            renderer.connect('edited', editableHandler)
        self.__appendNewColumn(column, renderer, True and model or str)
            
    def addImageColumn(self, name, visible, resizable, width = None):
        column, renderer = self.__addBaseColumn(name, "img", visible, resizable, width)
        column.set_attributes(renderer, icon_name = self.count["cols"])
        self.__appendNewColumn(column, renderer, str)
        
    def addProgressColumn(self, name, visible, resizable, width = None):
        column, renderer = self.__addBaseColumn(name, "pgr", visible, resizable, width)
        column.set_attributes(renderer, value = self.count["cols"])
        self.__appendNewColumn(column, renderer, float)
        
    def __appendNewColumn(self, column, renderer, model):
        self.columns[self.count["cols"]] = colStore(column, renderer, model)
        column.set_sort_column_id(self.count["cols"])
        self.count["cols"] += 1
        self.widget.append_column(column)
        self.__updateModelView()
            
    def __updateModelView(self):
        models = [colstore.model for colstore in self.columns.values()]
        self.store = self._createStore(models)
        self.widget.set_model(self.store)
        methods = {
            "headers-visible"  : "set_headers_visible",
            "headers-clickable": "set_headers_clickable",
            "rows-search"      : "set_enable_search",
            "rows-same-height" : "set_fixed_height_mode",
            "rows-alternate"   : "set_rules_hint",
            "rows-reorder"     : "set_reorderable",
        }
        for property, value in self.__features.items():
            getattr(self.widget, methods[property])(value)
            
    def _createStore(self, models):
        return gtk.TreeStore(*models)
            
    def mergeColumns(self, id, txt, img, pgr):
        column, renderer = self.columns[id].col, self.columns[id].rend
        if txt is not None:
            column.pack_start(self.columns[txt].rend)
            column.set_attributes(self.columns[txt].rend, text = txt)
        if img is not None:
            column.pack_start(self.columns[img].rend)
            column.set_attributes(self.columns[img].rend, icon_name = img)
        if pgr is not None:
            column.pack_start(self.columns[pgr].rend)
            column.set_attributes(self.columns[pgr].rend, value = pgr)
        
    def addRow(self, content, parent = None, position = None):
        try: parent = self.rows[parent].iter
        except: parent = None
        iter = (position 
            and self.store.insert(parent, position, content)
            or self.store.append(parent, content)
        )
        self.rows[self.count["rows"]] = rowStore(list(self.store)[-1:], iter)
        self.count["rows"] += 1
        
    def clearRows(self):
        self.store.clear()
        
    def getFlatRowDatas(self):
        content = []
        for row in [rowstore.row for rowstore in self.rows.values()]:
            content.append(list(row))
        return content
    
class genericListView(genericTreeView):
    
    def __init__(self, features):
        genericTreeView.__init__(self, features)
        
    def _createStore(self, models):
        return gtk.ListStore(*models)
        
    def addRow(self, content, position = None):
        iter = (position 
            and self.store.insert(position, content)
            or self.store.append(content)
        )
        self.rows[self.count["rows"]] = (list(self.store)[-1:], iter)
        self.count["rows"] += 1


class testSuite:
    
    def __init__(self):
        
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.connectEvents(self.window, {
             "delete_event" : self.delete,
             "destroy": self.destroy,
        })
        
        self.tree = genericTreeView({
            "headers-visible"  : True,
            "headers-clickable": True,
            "rows-search"      : False,
            "rows-same-height" : False,
            "rows-alternate"   : True,
            "rows-reorder"     : False,
        })
        
        self.tree.addImageColumn("Filename", True, True)
        self.tree.addTextColumn("-", str, False, False)
        self.tree.addTextColumn("Size", str, True, False, 50)
        self.tree.addTextColumn("Last Edit", str, True, True)
        self.tree.mergeColumns(0, 1, None, None)
                
        self.tree.addRow(["stock_folder", "usr", "4096", "aee"])
        self.tree.addRow(["stock_folder", "bin", "4096", "?"], parent = 0)
        self.tree.addRow(["stock_folder", "etc", "4096", "?"], parent = 0)
        self.tree.addRow(["stock_folder", "var", "4096", "?"], parent = 0)
        self.tree.addRow(["stock_folder", "local", "4096", "?"], parent = 0, position = 1)
        self.tree.addRow(["stock_folder", "bin", "4097", "beee"])
        
        self.tree.columns[0].rend.set_property('xalign', 1.0)
        self.tree.columns[0].col.set_sort_column_id(1)
        
        self.window.add(self.tree.widget)
        self.window.show_all()
    
    def connectEvents(self, widget, events):
        for type,callback in events.items():
            widget.connect(type, callback)

    def delete(self, widget, event, data=None):
        #print "delete event occurred"
        return False

    def destroy(self, widget, data=None):
        #print "destroy signal occurred"
        gtk.main_quit()
        
    def runTest(self):
        gtk.main()
        
if __name__ == "__main__": 
    GTK = testSuite()
    GTK.runTest()